package ru.ifmo.sound.jmlbased;

import ru.ifmo.sound.VectorGenerator;
import ru.ifmo.sound.WaveFile;
import ru.ifmo.sound.neuro.AllTheSystem;

import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import static ru.ifmo.network.SwingUtils.getBox;
import static ru.ifmo.network.SwingUtils.getLabeledComponent;

/**
 * @author avhaliullin
 */
public class MainApp {
    public static void main(String[] args) throws Exception {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        JFrame mainFrame = new JFrame();
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        if (JFileChooser.APPROVE_OPTION != fileChooser.showOpenDialog(mainFrame)) {
            System.exit(0);
        }

        final AllTheSystem theSystem = new AllTheSystem(fileChooser.getSelectedFile());
        mainFrame.setSize(400, 300);
        final JLabel error = new JLabel("0");
        JButton learnOnce = new JButton("Learn once");
        final AtomicBoolean running = new AtomicBoolean(false);
        final JButton continious = new JButton("Learn...");
        JButton stop = new JButton("Stop!");

        stop.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                running.set(false);
                continious.setEnabled(true);
            }
        });

        continious.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                running.set(true);
                new Thread(new Runnable() {
                    public void run() {
                        continious.setEnabled(false);
                        while (!Thread.interrupted() && running.get()) {
                            final float errorsCount = theSystem.fullCycle();
                            try {
                                SwingUtilities.invokeAndWait(new Runnable() {
                                    public void run() {
                                        error.setText(String.format("%.2f", errorsCount));
                                    }
                                });
                            } catch (InterruptedException e1) {
                                e1.printStackTrace();
                            } catch (InvocationTargetException e1) {
                                e1.printStackTrace();
                            }
                        }
                    }
                }).start();
            }
        });

        learnOnce.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                error.setText(String.format(String.format("%.2f", theSystem.fullCycle())));
            }
        });

        mainFrame.add(getBox(true,
                getBox(false, learnOnce, getLabeledComponent(error, "Errors count: ")),
                getBox(false, continious, stop),
                new SongHandler(theSystem)));

        mainFrame.setVisible(true);
    }

    static class SongHandler extends JPanel {
        private final JSlider slider = new JSlider();
        private WaveFile waveFile;
        private final JLabel found = new JLabel("");

        private void openFile(File file) {
            try {
                waveFile = new WaveFile(file);
            } catch (UnsupportedAudioFileException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            slider.setMaximum((int) (waveFile.getDurationTime() - VectorGenerator.getCheckedIntervalSeconds()));

        }

        public SongHandler(final AllTheSystem theSystem) {
            slider.setVisible(false);
            final JLabel sliderValue = new JLabel();
            slider.addChangeListener(new ChangeListener() {
                public void stateChanged(ChangeEvent e) {
                    sliderValue.setText(String.format("%ds", slider.getValue()));
                }
            });
            final JFileChooser fileChooser = new JFileChooser();
            final JTextField fileName = new JTextField();
            fileName.setEnabled(false);
            fileName.setDisabledTextColor(Color.black);
            final JButton check = new JButton("Check");
            check.setEnabled(false);
            check.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    Map<String, Boolean> res = theSystem.analyze(VectorGenerator.generate(waveFile, VectorGenerator.getShiftBySeconds(waveFile, slider.getValue())));
                    StringBuilder sb = new StringBuilder();
                    for (Map.Entry<String, Boolean> entry : res.entrySet()) {
                        if (entry.getValue()) {
                            sb.append(entry.getKey()).append(" ");
                        }
                    }
                    found.setText(sb.toString());
                }
            });

            JButton browse = new JButton("Browse");
            browse.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    fileChooser.setFileFilter(new FileFilter() {
                        @Override
                        public boolean accept(File f) {
                            return f.getName().toLowerCase().endsWith(".wav") || f.isDirectory();
                        }

                        @Override
                        public String getDescription() {
                            return "*.wav";
                        }
                    });
                    int res = fileChooser.showOpenDialog(SongHandler.this);
                    if (res == JFileChooser.APPROVE_OPTION) {
                        slider.setVisible(true);
                        check.setEnabled(true);
                        fileName.setText(fileChooser.getSelectedFile().getAbsolutePath());
                        openFile(fileChooser.getSelectedFile());
                    }
                }
            });
            add(getBox(true,
                    getBox(false, fileName, browse),
                    getBox(false, slider, sliderValue),
                    check,
                    getLabeledComponent(found, "Found: ")));
        }

    }

}
